--- This module provides 'http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf JSON support' for Frege.
{--
    JSON support comprises 4 levels:

    1. On the lexical level, we analyze a 'String' and produce a list of JSON 'Token's.
    2. On the grammar level, we parse a list of 'Token's and produce a JSON 'Value',
       the internal representation of JSON data.
       (It is also possible to write custom parsers that produce values
       of certain data types directly.)
    3. On the value level, we convert JSON 'Value's to and from values of algebraic data types.
       This is accomplished by type classes 'ToJSON' and 'FromJSON'. Instances for basic types,
       in particular for all tuple types, are provided.
    4. On the presentation level, a JSON 'Value' is rendered as 'String' 
       that conforms to the JSON standard and can thus be used to exchange data
       with other software or over the internet.

    The users of this library can get full JSON support by concentrating on the
    third point, which essentially means that they have to write 'FromJSON' and 'ToJSON'
    instances for their data types. It follows a short tutorial on how to do this.

    ## Encoding of algebraic data types in JSON

    The following suggestions will foster a compact and easy to decode 'String'
    representation of Frege data. Derived instances for FromJSON/ToJSON comply
    with them:

    - 'Bool', numbers, 'String': @true@, @false@, _number_, "_string_"
    - a 'Char' _c_ will be encoded as JSON string "_c_"
    - lists, arrays and the like: @[ value0, value1, ... ]@
    - the trivial type @()@: @[]@
    - tuples and other product types: @[ field1, field2, ... ]@
    - enumerations: the constructor name as string
    - type renamings: same as the wrapped type
    - algebraic types: for each variant, make a JSON struct with the
      constructor name as key. Example:
      > { "Just": 42 }
      > {"Nothing":null}
    - If there is more than one component for the constructor, treat
      the values as tuple: 
      > { "Data": [field1,field2,...]}. 
    - A record could also get encoded like: 
      > { "case":"Person", "name":"Smith", "age":42}
    - inside @[]@ or @{}@ brackets, 'Maybe' values can be abbreviated 
      in such a way that @null@ stands for 'Nothing' and @v@ for 'Just' v, but
      observe that values of type @(Maybe (Maybe x))@ cannot be encoded like this, 
      because there would be no encoding for the value @Just Nothing@. 

    ## Create JSON documents from your data

    This will be done in two steps:
    
    1. Convert your data to JSON 'Value's, the internal generic representation
        for JSON data provided by this module.
    2. Show the JSON 'Value'. This results in a 'String' which is a standard
        conforming JSON document.
    
    The conversion should be done by implementing type class 'ToJSON' for your data.
    There is just one class operation 'toJSON' to implement.
    
    Because standard Frege types, lists, arrays and all tuple types are already
    instances of 'ToJSON', this is easy to accomplish, as will be demonstrated
    below.   

    Given the following definitions:
    >  data Engine = Electric Double --- just performance in kW
    >               | Combustion { fuel :: [Fuel], displacement :: Double, cyls :: Int }
    >  data Fuel = DIESEL | GASOLINE | NATURALGAS | LPG
    >  data Vehicle = Vehicle { wheels :: Int, engine :: Maybe Engine }
    we could make the following instances:
    
    > derive Show Fuel      -- we need this in the ToJSON instance

    Use the 'Value.String' constructor to create a JSON string value 
    from an ordinary 'String'.

    > instance ToJSON Fuel where
    >    toJSON = String . show

    The instance for @Engine@ makes JSON structs for the @Engine@ constructors
    by associating the constructor name with the values under the constructor.
    There is a function 'struct', designed to create such structures that have just
    a single association, which is - according to our encoding suggestions -
    a most frequent case.

    > instance ToJSON Engine where
    >    toJSON (Electric d) 
    >            = struct "Electric" d
    >    toJSON Combustion{fuel, displacement, cyls}
    >            = struct "Combustion" (fuel, displacement, cyls)
    
    The @Vehicle@ instance demonstrates a more complex JSON struct, where 
    the record field names are associated with their values. The 'Struct'
    constructor takes a list of associations, created with 'assoc'.
    The constructor name is redundant here, as @Vehicle@ is a product type,
    so it is not included.
    
    If we have 'Maybe' values in the struct that are actually 'Nothing', 
    we can as well omit their associations
    and thus reduce the size of the generated JSON. 
    However, the corresponding
    'fromJSON' function will then have to interpret a missing association as
    'Nothing' - this is exactly the purpose of the 'optional' function.
 
    > instance ToJSON Vehicle where
    >    {-- For illustration, we use a struct with record fields
    >    
    >       The first clause is not strictly necessary, 
    >       but helps to reduce the generated json size
    >       in the case that we have no engine, by just not
    >       producing an association for "engine".
    >    
    >       This assumes that the corresponding 'fromJSON' function takes care of that,
    >       preferably by extracting the "engine" field with 'optional'.
    >   -}
    >    toJSON Vehicle{wheels, engine=Nothing} 
    >           = Struct [ assoc "wheels" wheels ]   -- just leave out engine
    >    toJSON Vehicle{wheels, engine} 
    >            = Struct [
    >                    assoc "wheels" wheels,
    >                    -- uses the short form for Maybe
    >                    assoc "engine" (maybeToJSON engine), 
    >            ]

    We can now construct some vehicles and print a JSON document. 
    The translation of the internal to the external (i.e. 'String') form
    is done by the 'Show' instance for JSON 'Value's.
    
    > bicycle = Vehicle { wheels = 2, engine = Nothing }
    > ebike   = Vehicle { wheels = 2, engine = Just (Electric 0.9) }
    > car     = Vehicle { wheels = 4, 
    >                     engine = Just Combustion {
    >                              fuel = [LPG, GASOLINE], 
    >                              displacement = 2.0,
    >                              cyls = 4 }}
    > vehicles = [car, bicycle, ebike]
    > main = println (toJSON vehicles)
    
    The output looks like:
    
    > [{
    >  "wheels" : 4,
    >  "engine" : {"Combustion" : [["LPG", "GASOLINE"], 2.0, 4]}
    > },
    > {"wheels" : 2, "engine" : null},
    > {"wheels" : 2, "engine" : {"Electric" : 0.9}}]


    ## Reconstruct your data from JSON data
    
    There are 2 ways one could get confronted with JSON data:
    
    1. A JSON document in the form of a 'String'
    2. A JSON 'Value'
    
    The type class 'FromJSON' has two operations to deal with those scenarios: 
    'parseJSON' and 'fromJSON'. But only the latter one needs to be implemented, 
    the default implementation of 'parseJSON' will parse a 'String' to a generic
    JSON 'Value' and pass this to 'fromJSON'.
    
    While it may cost a bit of memory to first create the JSON 'Value', this
    two-step approach has a number of advantages. Not the least one being clear
    separation of lexical and syntactical issues from semantical ones. But it
    is also the case that writing 'fromJSON' functions is quite easy, 
    if not boring. The type checker, the support for basic types, lists and tuples
    and the internal plumbing make it hard to write a wrong implementation.
    Whereas writing a parser is comparatively hard and error prone.

    ### Implementing 'fromJSON'
    
    Reconstruction of values from JSON data can fail, 
    therefore the 'fromJSON' function delivers its result in a failure monad
    ('MonadFail' - two well known failure monads are 'Maybe' and 'Either' 'String').
    'fromJSON' is therefore overloaded twice in the return type: one for the
    actual data type and then the monad.  
    
    If one has already a 'ToJSON' instance, it should go without saying
    that the implementations should satisfy the following law:
    
    > decodeEncoded x = fromJSON (toJSON x) == Just x

    Here are, in continuation of our example from above, the 'FromJSON' instances:

    > instance FromJSON Fuel where
    >     fromJSON (String "DIESEL") = return DIESEL
    >     fromJSON (String "GASOLINE") = return GASOLINE
    >     fromJSON (String "NATURALGAS") = return NATURALGAS
    >     fromJSON (String "LPG") = return LPG
    >     fromJSON s = fail ("cannot decode fuel from " ++ show s)

    Note the use of 'fail' and 'return' which is needed because we produce
    our value in a failure monad like 'Maybe' or 'Either' 'String'. In fact, 
    every correct implementation of 'fromJSON' will have at least two equations 
    (or, equivalently, case alternatives) where at least one does 'fail' and 
    at least one is 'return'ing an actual value.  

    > import Data.List(lookup)  -- for looking up associations
    > instance FromJSON Engine where
    >    fromJSON (Struct as)
    >       | Just n   <- lookup "Electric" as   = Electric <$> fromJSON n
    >       | Just fdc <- lookup "Combustion" as = do
    >               (fuel, displacement, cyls) <- fromJSON fdc
    >               return Combustion{fuel, displacement, cyls}
    >    fromJSON x = fail ("invalid engine: " ++ show x)
    
    We need to look up the keys to find out which variant we have. We then
    just decode the associated values and recreate our value. Failures
    for sub-components are propagated upwards automatically, thanks to the 
    monadic approach. For example, when we try to decode an engine from
    
    > { "Combustion" : [ ["Water"], 2.7, 3]}
    
    we will get the error 
    
    > cannot decode fuel from "Water"
    
    Because the fuel cannot get decoded, the decoding of the 3-tuple fails, and
    our combustion engine will not be constructed.  
    
    Note how the existence of generic 'FromJSON' instances for primitives, 
    tuples and lists makes the decoding a no brainer. 
    
    Finally we can decode vehicles:
    
    > instance FromJSON Vehicle where
    >   fromJSON (Struct as)  = do
    >       wheels ← field    "wheels" as
    >       engine ← optional "engine" as
    >       pure Vehicle{wheels, engine}
    >   fromJSON garbage = fail ("couldn't decode Vehicle from: " ++ show garbage)

    The 'field' function extracts a field from an association list, or fails with an
    appropriate message. The "engine" field has type ('Maybe' Engine) and could be extracted
    with the 'field' function as well, but a missing "engine" association would then
    mean failure. 
    With 'optional', a missing "engine" association means that "engine" is 'Nothing'.
         
    Observe that this instance allows the following: 
    1. key/value pairs can occur in any order
    2. additional keys besides @"wheels"@ and @"engine"@ are ignored
    3. the "engine" key can be missing, and this will be interpreted as a
        vehicle without engine.

    Such a forgiving and fault-tolerant implementation is oftentimes in order.
    However, if one needs it stricter, one can pattern match the association
    list directly:
    
    > fromJSON (Struct [("wheels", jw), ("engine", je)]) = do
    >                  wheels <- fromJSON jw
    >                  engine <- fromJSON je
    >                  return Vehicle{wheels, engine}

    To read a vehicle from a 'String',
    we just need to run the automatically supplied 'parseJSON' function:
    
    >  case parseJSON "{\"wheels\" : 3 }"  of
    >       Just Vehicle{wheels=w} -> -- we have w wheels ...
    
    Like with 'fromJSON', 
    the 'parseJSON' function needs to know the type of the item to decode as
    well as the failure monad to work with. Most often, this can be inferred
    by the compiler, like in the example above where it is clear that we want
    a @Maybe Vehicle@.
 
    ### Very brief guide to 'Parser's
    
    Sometimes memory and time are extremely scarce, and the data to decode
    are comparatively simple. This is the time to roll your own custom 
    JSON parser.
    
    The parsers provided in this module fall into 4 classes:
    1. 'Parser' 'Value' are not interesting for custom parser builders, because 
    they are used to implement the generic 'Value' parsers. (The source code
    could give some inspiration, though ...)
    2. 'Parser' 'Token' such as 'parseComma', 'parseColon' and so on parse 
    punctuation occurring in JSON syntax, and can be re-used in any other parser.
    3. 'Parser' _a_ where _a_ is some basic type like 'Bool', 'Int' or 'String'. 
    You most likely want to reuse those in your custom parser.
    4. 'Parser' combinators like 'parsePair', 'parseTuple' and 'parseList' 
    take one or two parsers as arguments and build parsers for more
    complex structures that contain the provided ones.
    
    All 'Parser's supported by this module operate on list of 'Token's. 
    The function 'lexer' can be used to turn a 'String' into such a list, 
    obeying the JSON lexical syntax. Finally, the function 'runParser' 
    actually applies a parser to a token list.
    
    So the skeleton of your code should read like this example:
    
    > run :: MonadFail m => String -> m [Float] 
    > run = runParser custom . lexer 
    >        where custom = parseList parseFloat
    
    The "custom parser" here parses a list of floating point values, and
    on success returns a @[Float]@ in the failure monad of your choice.
 
-}
module frege.data.JSON where

import frege.Prelude hiding(null)
import Data.Bits (shiftL, .|.)
import Data.MicroParsec as MP(cond, failure, eos, expect, satisfy, <?>, sepBy1)
import Lib.PP(bracket, text, sep, pretty, stack)
import Data.List (sortBy, lookup)

--- lexical entities that can appear in a JSON String
protected data Token = 
      protected BRACEL                  --- left brace @{@
    | protected BRACER                  --- right brace @}@
    | protected BRACKL                  --- left bracket @[@
    | protected BRACKR                  --- right bracket @]@
    | protected COLON                   --- colon @:@
    | protected COMMA                   --- comma @,@
    | protected S {!sval ∷ String}      --- a JSON string, escapes already decoded
    | protected N {!nval ∷ String}      --- a JSON number, 'atod' will work
    | protected TRUE                    --- @true@
    | protected FALSE                   --- @false@
    | protected NULL                    --- @null@ (o noes!!!)
    | protected ERROR  {!offset ∷ Int, 
                        !text   ∷ String}   --- lexical error indicator

instance Show Token where
    show Token.BRACEL = "{"
    show Token.BRACER = "}"
    show Token.BRACKL = "["
    show Token.BRACKR = "]"
    show Token.COLON  = ":"
    show Token.COMMA  = ","
    show Token.TRUE   = " true "
    show Token.FALSE  = " false "
    show Token.NULL   = " null "
    show (Token.S s)  = show s
    show (Token.N n)  = n
    show Token.ERROR{offset, text} = "`%s` at offset %d".format text offset
    
derive Eq Token

{--
    Translate a 'String' into a lazy list of 'Token's.

    There will be at most one 'Token.ERROR' token in the result, 
    and it will be the last in the list. This is, the 'lexer' will stop
    on the first lexical error.
    
    Absence of lexical errors does not mean valid JSON, for example
    > "null, true,"
    is lexed as
    > [NULL, COMMA, TRUE, COMMA]
    but is, of course invalid.
-} 
lexer :: String -> [Token]
lexer s = lex s 0

{--
    Scan a 'String' and take care of offsets
-}
private lex :: String → Int → [Token]
private lex !cs !start
    | endOfSeq        = []
    | ch.isWhitespace = lex cs (start+1)    -- handles tabs, carriage return and newlines as well
    | ch.isDigit      = case positive 0 of
                            !after | after > 0 
                                      → Token.N{nval = seq (start+after)} !: lex cs (start+after)
                            otherwise → Token.ERROR{offset=start, text=seq (start+1)} !: []
    | otherwise = case ch of
        '"' →   string 1 []
        '-' →   case positive 1 of
                    !after | after > 0 
                              → Token.N{nval = seq (start+after)} !: lex cs (start+after)
                    otherwise → Token.ERROR{offset=start, text=seq (start+1)} !: []
        ',' →   Token.COMMA  : lex cs (start+1) 
        ':' →   Token.COLON  : lex cs (start+1)
        '{' →   Token.BRACEL : lex cs (start+1) 
        '}' →   Token.BRACER : lex cs (start+1)
        '[' →   Token.BRACKL : lex cs (start+1) 
        ']' →   Token.BRACKR : lex cs (start+1)
        -- the following lexes "truenull" as TRUE:NULL:...
        -- and "true0" as TRUE:N "0":...
        -- but this will yield syntax error later
        't' | at 1 == 'r', at 2 == 'u', at 3 == 'e'
            →   Token.TRUE : lex cs (start+4)
        'f' | at 1 == 'a', at 2 == 'l', at 3 == 's', at 4 == 'e'
            →   Token.FALSE : lex cs (start+5)
        'n' | at 1 == 'u', at 2 == 'l', at 3 == 'l'
            →   Token.NULL : lex cs (start+4)
        _   →   Token.ERROR{offset=start, text=seq (start+1)} !: []        -- abort scanning
    where
        !endOfSeq   = start >= cs.length      -- assume that length is a cheap operation on Strings
        !ch         = at 0
        seq end     = (cs.substr start end)
        at i        = if start+i >= cs.length then '\0' else cs.charAt (start+i)
        positive off
            | at off == '0'     → fractional (off+1)
            | (at off).isDigit  → fractional (digits (off+1))
            | otherwise         → -1 
        digits off  -- skip 0 or more digits
            | (at off).isDigit  → digits (off+1)
            | otherwise         → off
        fractional off
            | at off == '.'     → if (at (off+1)).isDigit 
                                    then expo (digits (off+2))
                                    else -1
            | otherwise         → expo off
        expo off = case at off of
                'e'     → expo1 (off+1)
                'E'     → expo1 (off+1)
                _       → off   -- no exponent
        expo1 off = case at off of
            '+' → expo2 (off+1)
            '-' → expo2 (off+1)
            _   → expo2 off
        -- at least 1 digit 
        expo2 off = if (at off).isDigit then digits (off+1) else -1     
        string off !acc
            | ch == '"'     → Token.S{sval=packed (reverse acc)} !: lex cs (start+off+1)
            | ch == '\\'    → case at (off+1) of
                                '"' → string (off+2) ('"'  : acc)
                                '\\'→ string (off+2) ('\\' : acc)
                                '/' → string (off+2) ('/'  : acc)
                                'b' → string (off+2) ('\b' : acc)
                                'f' → string (off+2) ('\f' : acc)
                                'n' → string (off+2) ('\n' : acc)
                                'r' → string (off+2) ('\r' : acc)
                                't' → string (off+2) ('\t' : acc)
                                'u' | Just h1 ← hexval (at (off+2)),
                                      Just h2 ← hexval (at (off+3)),
                                      Just h3 ← hexval (at (off+4)),
                                      Just h4 ← hexval (at (off+5)),
                                      !hex <- h1 `shiftL` 12 
                                                .|. h2 `shiftL` 8
                                                .|. h3 `shiftL` 4
                                                .|. h4
                                    → string (off+6) (chr hex !: acc)
                                other ->  Token.ERROR{offset=start+off+1, text=seq (start+off+2)} !: []
            | ch >= ' '     → string (off+1) (ch : acc)
            | start+off >= cs.length
                            → Token.ERROR{offset=start+off, text=seq (cs.length)}   !: []
            | otherwise     → Token.ERROR{offset=start+off, text=seq (start+off+1)} !: []  
            where
                !ch = at off
                j :: Int -> Maybe Int
                j !x = Just x
                hexval c
                    | c >= '0' && c <= '9' = j (ord c - ord '0')
                    | c >= 'a' && c <= 'f' = j (10 + (ord c - ord 'a'))
                    | c >= 'A' && c <= 'F' = j (10 + (ord c - ord 'A'))
                    | otherwise = Nothing

--- Internal representation of JSON data
data Value = 
      String  String                        --- a string
    | Number  String                        --- a number
    | Bool    Bool                          --- @true@ or @false@   
    | Null                                  --- just @null@
    | Array  [Value]                        --- > [ value, ... ]
    | Struct [(String,Value)]               --- > { "name":value, ... }
    where
        --- singleton JSON @true@ constant
        !jTrue  = Bool true
        --- singleton JSON @false@ constant
        !jFalse = Bool false

--- Make a single association 
assoc ∷ ToJSON b ⇒ String → b → (String, Value)
assoc k v = (k, toJSON v)

--- Make a 'Struct' with just a single association, suitable for variants
struct ∷ ToJSON a ⇒ String → a → Value
struct k v = Struct [assoc k v]

--- Extract a required field from an association list or 'fail' with an appropriate message. 
field ∷ (FromJSON b, MonadFail m) ⇒ String → [(String, Value)] → m b
field s = maybe 
            (fail ("required field \"" ++ s ++ "\" is missing."))
            fromJSON
        . lookup s 

--- Convenience function for optional fields, use like
--- >  foo ← optional  "foo" s
--- This will decode any of the following
--- > { ... }                       -- no "foo" in structure, hence Nothing
--- > { ..., "foo" : null, ... }    -- again, foo is Nothing
--- > { ..., "foo" : {"Nothing" : null}, ...} --- again Nothing
--- > { ..., "foo" : 42, ...}       -- foo is Just 42
--- > { ..., "foo" : {"Just" : 42}} -- foo is Just 42 
 
optional ∷ (FromJSON α, MonadFail m) ⇒ String → [(String, Value)] → m (Maybe α)
optional s = maybe (pure Nothing) fromJSON . lookup s

--- Convenience function to do 'fromJSON' in the 'Maybe' monad.
fromJSONMaybe ∷ FromJSON b ⇒ Value → Maybe b
fromJSONMaybe = fromJSON

--- Convenience function to do 'fromJSON' in the 'Either' monad.
fromJSONEither ∷ FromJSON b ⇒ Value → Either String b
fromJSONEither = fromJSON


--- A JSON parser processes a list of 'Token's.
type Parser = MP.Parser [] Token

--- run a 'Parser' and extract the result 
runParser :: Parser a -> [Token] -> (String | a)
runParser p ts = case MP.runid p ts of
    (Left msg, ts) →  Left (MP.reporterror ts msg)
    (right, _)     →  right  

-- parse a 'String' into a JSON 'Object'
-- parseJSON = parse object . lexer

-- parse a 'String' into a JSON 'Value'
-- parseValue = runParser value . lexer

--- Parses an 'Array' or a 'Struct'
--- This is the parser that will be used in type class 'FromJSON' by default.
--- This parser fails unless it could consume all input.
parseObject :: Parser Value
parseObject =
    cond  (parseLbrack <|> parseLbrace)
        (parseArray <|> parseStruct) 
        (failure "JSON object or JSON array expected")
    <* eos  

--- parse any JSON value
parseValue  ∷ Parser Value
parseValue = (
            String <$> parseString
        <|> parseNumber
        <|> parseNull
        <|> parseBoolean
        <|> parseArray
        <|> parseStruct)
    <?> "JSON value expected" 

--- Parse a JSON number
parseNumber :: Parser Value
parseNumber = Value.Number . _.nval <$> satisfy _.{nval?}

--- Parse a JSON boolean
parseBoolean ∷ Parser Value
parseBoolean = 
            const (Value.jTrue)  <$> expect Token.TRUE 
        <|> const (Value.jFalse) <$> expect Token.FALSE  

--- Parse JSON @null@
parseNull :: Parser Value
parseNull = const Value.Null <$> expect Token.NULL

--- Parse a JSON array
parseArray ∷ Parser Value
parseArray = Array <$> parseList parseValue

--- Parse a JSON struct
--- If one and the same key appears multiple times, only the last one will be taken into account.
parseStruct ∷ Parser Value
parseStruct = do
    parseLbrace
    cond parseRbrace 
        (parseRbrace >> return (Struct empty)) 
        do
            ps ← parsePair parseValue `sepBy1` parseComma
            parseRbrace
            (return . Struct) ps

--- parse a left bracket
parseLbrack  ∷ Parser Token
parseLbrack = expect Token.BRACKL <?> "'[' expected"

--- parse a left brace
parseLbrace  ∷ Parser Token
parseLbrace = expect Token.BRACEL <?> "'{' expected"

--- parse a right bracket
parseRbrack  ∷ Parser Token
parseRbrack = expect Token.BRACKR <?> "']' missing"

--- parse a right brace
parseRbrace  ∷ Parser Token
parseRbrace = expect Token.BRACER <?> "'}' missing"

--- parse a comma
parseComma  ∷ Parser Token
parseComma = expect Token.COMMA <?> "',' expected"

--- parse a colon
parseColon ∷ Parser Token
parseColon = expect Token.COLON <?> "':' expected"

--- parse a 'String'
parseString :: Parser String
parseString = _.sval <$> satisfy _.{sval?}

--- parse an 'Int'
parseInt :: Parser Int
parseInt = satisfy _.{nval?} >>= either (const pzero) return . String.int . Token.nval 

--- parse a 'Long'
parseLong :: Parser Long
parseLong = satisfy _.{nval?} >>= either (const pzero) return . String.long . Token.nval 

--- parse an 'Integer'
parseInteger :: Parser Integer
parseInteger = satisfy _.{nval?} >>= either (const pzero) return . String.integer . Token.nval 

--- parse a raw 'Double'
parseDouble :: Parser Double
parseDouble = satisfy _.{nval?} >>= either (const pzero) return . String.double . Token.nval 

--- parse a raw 'Float'
parseFloat :: Parser Float
parseFloat = satisfy _.{nval?} >>= either (const pzero) return . String.float . Token.nval 

--- parse a 'Bool'
parseBool ∷ Parser Bool
parseBool = const true  <$> expect Token.TRUE
        <|> const false <$> expect Token.FALSE



--- parse a pair @"string" : v@
parsePair :: Parser v → Parser (String, v)
parsePair with = do
    k <- parseString <?> "string expected"
    parseColon
    v <- with
    return (k,v)

--- parse a list
--- For example, 
--- > parseList parseFloat
--- produces a [Float] directly
parseList :: Parser a -> Parser [a]
parseList pElem = do
    parseLbrack
    cond parseRbrack 
        (parseRbrack >> return []) 
        do 
            vs <- pElem `sepBy1` parseComma
            parseRbrack
            return  vs

--- parse a raw tuple
--- Use like
--- > parseTuple (parseFloat, parseString)
--- This would produce @(Float, String)@
parseTuple ∷ (Parser a,Parser b) → Parser (a,b)
parseTuple (pA, pB) = do
    parseLbrack
    a <- pA
    parseComma
    b <- pB
    parseRbrack
    return (a,b)

{--
    Pretty print a 'Value'.
    
    This is used in the 'Show' instance for 'Value', but can be useful otherwise.
    For example, to print a large 'Value' directly to 'stdout' without
    realizing the full intermediate 'String' in memory with a line width of 
    120 use:
    > import Lib.PP(prettyIO)
    > prettyIO stdout 120 . valDoc
-} 
valDoc :: Value -> PP.DOCUMENT 
valDoc v = case v  of
    String sval  → text (show sval)
    Number nval  → text nval
    Bool   bval  → text (display bval)
    Null         → text "null"
    Array a      → bracket "[" (sep "," (map valDoc a)) "]" 
    Struct s     → bracket "{" (sep "," pairs) "}"
                where 
                    pairs = map pairDoc s
                    pairDoc (s,v) = PP.group $ text (show s) PP.<+> text ":" PP.<+> valDoc v


instance Show Value where
    show = pretty 72 . valDoc

instance Eq Value where
    hashCode _ = -1
    String a == String b = a == b
    Number a == Number b = a == b
    Bool   a == Bool   b = a == b
    Null     == Null     = true
    Array  a == Array  b = a == b 
    Struct m == Struct p = em == ep
        where
            em = sortBy (comparing fst) m
            ep = sortBy (comparing fst) p
    _ == _ = false

{--
    Class of types whose values can be reconstructed from JSON.

    There are two ways to accomplish this:

    1. take a JSON 'Value' and try to reconstruct a value of the desired type,
       that is, implement function 'fromJSON'
    2. write a 'Parser' that produces the desired value directly and use
       this to implement 'parseJSON'

    The usual way is to implement 'fromJSON' and keep the default for 'parseJSON', 
    which parses a 'String' to a  'Value' and passes that value to 'fromJSON'.

    Minimal complete definition: 'fromJSON'

    The instances of all standard types that are not encoded as objects will
    have an implementation of 'parseJSON' that fails immediately. This behaviour 
    is in line with the JSON standard which allows only objects
    (that is, maps or arrays) to appear on the top level.

-}
class FromJSON a where
    {-- 
        Interpret a JSON value as a value of the instance type, or 'fail'.

        This function must be implemented by all instances.

        If one has a non-standard implementation of 'parseJSON' that does
        not use 'fromJSON', a conforming, but inefficient implementation would be

        > fromJSON = parseJSON . show 
    -}
    fromJSON  ∷ MonadFail m ⇒ Value → m a
    
    {--
        Parse a 'String' which must contain valid JSON, and interpret
        as value of the instance type.

        The standard implementation uses 'parseObject' to make a JSON
        'Value' that is passed on to 'fromJSON'.
    -}
    parseJSON ∷ MonadFail m ⇒ String → m a
    parseJSON = either fail fromJSON . runParser parseObject . lexer  

{--
    The class of types that support their serialization to JSON.

    Note that the JSON value for primitive types and 'String's yields no
    valid JSON document when printed.
-}
class ToJSON a where
    toJSON :: a -> Value

instance ToJSON Value where
    toJSON = id

instance FromJSON Value where
    fromJSON = return



instance ToJSON () where
    toJSON () = Array []

instance FromJSON () where
    fromJSON (Array  xs)
        | xs.null   = return ()
        | otherwise = fail ("cannot decode () from non empty array")
    fromJSON other  = fail ("cannot decode () from " ++ show other)


instance ToJSON Bool where
    toJSON b = if b then Value.jTrue else Value.jFalse

instance FromJSON Bool where
    fromJSON (Bool bval)      = return bval
    fromJSON other            = fail ("cannot decode Bool from " ++ show other)
    parseJSON _               = fail ("A top level JSON value cannot be Bool")


instance ToJSON Byte where
    toJSON b = Number (show b.unsigned)

instance FromJSON Byte where
    fromJSON (Number nval) = either (fail . Throwable.show) checkbyte . String.int $ nval
        where
            checkbyte n 
                | n > Byte.maxBound.unsigned = fail ("%d too big for byte".format n)
                | n < Byte.minBound.unsigned = fail ("%d too small for byte".format n)
                | otherwise = return (byte n)
    fromJSON other              = fail ("cannot decode Byte from " ++ show other)
    parseJSON _                 = fail ("A top level JSON value cannot be Byte")


instance ToJSON Short where
    toJSON s = Number (show s.unsigned)

instance FromJSON Short where
    fromJSON (Number nval) = either (fail . Throwable.show) checkshort . String.int $ nval
        where
            checkshort n 
                | n > Short.maxBound.unsigned = fail ("%d too big for short".format n)
                | n < Short.minBound.unsigned = fail ("%d too small for short".format n)
                | otherwise = return (short n)
    fromJSON other              = fail ("cannot decode Short from " ++ show other)
    parseJSON _                 = fail ("A top level JSON value cannot be Short")


instance ToJSON Int where
    toJSON i = Number (show i)

instance FromJSON Int where
    fromJSON (Number nval)  = either (fail . Throwable.show) return . String.int $ nval
    fromJSON other          = fail ("cannot decode Int from " ++ show other)
    parseJSON _             = fail ("A top level JSON value cannot be Int")


instance ToJSON Long where
    toJSON i = Number (show i)

instance FromJSON Long where
    fromJSON (Number nval)  = either (fail . Throwable.show) return . String.long $ nval
    fromJSON other          = fail ("cannot decode Long from " ++ show other)
    parseJSON _             = fail ("A top level JSON value cannot be Long")


instance ToJSON Integer where
    toJSON i = Number (show i)

instance FromJSON Integer where
    fromJSON (Number nval)  = either (fail . Throwable.show) return . String.integer $ nval
    fromJSON other          = fail ("cannot decode Integer from " ++ show other)
    parseJSON _             = fail ("A top level JSON value cannot be Integer")


instance ToJSON Float where
    toJSON i = Number (show i)

instance FromJSON Float where
    fromJSON (Number nval)  = either (fail . Throwable.show) return . String.float $ nval
    fromJSON other          = fail ("cannot decode Float from " ++ show other)
    parseJSON _             = fail ("A top level JSON value cannot be Float")


instance ToJSON Double where
    toJSON i = Number (show i)

instance FromJSON Double where
    fromJSON (Number nval)  = either (fail . Throwable.show) return . String.double $ nval
    fromJSON other          = fail ("cannot decode Double from " ++ show other)
    parseJSON _             = fail ("A top level JSON value cannot be Double")


instance ToJSON Char where
    toJSON c = String (ctos c)

instance FromJSON Char where
    fromJSON (String sval) | length sval == 1 
                                = return (sval.charAt 0)
    fromJSON other              = fail ("cannot decode Char from " ++ show other)
    parseJSON _                 = fail ("A top level JSON value cannot be Char")


instance ToJSON String where
    toJSON s = Value.String s

instance FromJSON String where
    fromJSON (String sval)  = return sval
    fromJSON other          = fail ("cannot decode String from " ++ show other)
    parseJSON _             = fail ("A top level JSON value cannot be String")


instance ToJSON e ⇒ ToJSON [e] where
    toJSON = Array . map toJSON 

instance (FromJSON e) ⇒ FromJSON [e] where
    fromJSON (Array xs)
                                    -- goes 3 times through the list
                                    -- but avoids implicit construction
                                    -- of intermediate lists through mapM 
                                = if all (either (const false) (const true)) js
                                    then return     [ e | Right e ← js ]
                                    else fail (head [ e | Left e  ← js ])
                       where js = map fromJSON xs
    fromJSON other              = fail ("cannot decode [] from non array " ++ show other)


instance ToJSON e ⇒ ToJSON (JArray e)  where
    toJSON = Array . map maybeToJSON . genericToMaybeList

instance (FromJSON e, ArrayElement e) ⇒ FromJSON (JArray e) where
    fromJSON list = arrayFromMaybeList <$> fromJSON list


--- 'Maybe.toJSON' produces one of
--- > {"Nothing" : null }
--- > {"Just"    : v }
--- For a more concise representation see 'maybeToJSON'
instance ToJSON e ⇒ ToJSON (Maybe e) where
    toJSON = maybe nothingJSON (struct "Just")

--- constant @{"Nothing" : null}@, used in encoding 'Maybe' values
private nothingJSON :: Value  -- [(String, Value)]
private !nothingJSON = struct "Nothing"  Value.Null


--- The short encoding for 'Maybe' values.
--- Produces 'Null' for 'Nothing' and the jsonized value for 'Just' value.
--- The 'FromJSON' instance for 'Maybe' is prepared to deal with the different encodings.
maybeToJSON ∷ ToJSON a ⇒ Maybe a → Value
maybeToJSON = maybe Null toJSON

instance (FromJSON e) ⇒ FromJSON (Maybe e)  where
    {--
        Encoding can be:
        > {"Just": some-value}
        > {"Nothing": _}
        > null
        > some-value 
    -}
    fromJSON (Struct m)
        | Just v <- lookup "Just"     m = Just <$> fromJSON v
        | Just _ <- lookup "Nothing"  m = return Nothing
    fromJSON Value.Null                 = return Nothing
    fromJSON v                          = Just <$> fromJSON v


instance (ToJSON a, ToJSON b) ⇒ ToJSON (a|b)  where
    toJSON = either (struct "Left") (struct "Right")


instance  (FromJSON a, FromJSON b) ⇒ FromJSON (a|b)  where
    fromJSON (Struct m)
        | Just v <-  lookup "Left"   m  = Left  <$> fromJSON v
        | Just v <-  lookup "Right"  m  = Right <$> fromJSON v
    fromJSON other                      = fail ("cannot decode Either from " ++ show other)


instance  (ToJSON a, ToJSON b) ⇒ ToJSON (a, b)  where
    toJSON (a,b) = Array [toJSON a, toJSON b]

instance (FromJSON a, FromJSON b) ⇒ FromJSON  (a, b) where
    fromJSON (Array [va, vb]) = do
        a ← fromJSON va
        b ← fromJSON vb
        return (a,b)
    fromJSON other      = fail ("cannot decode (a,b) from " ++ show other)

instance  (ToJSON a, ToJSON b, ToJSON c) ⇒ ToJSON (a, b, c) where
    toJSON (a,b,c) = Array [toJSON a, toJSON b, toJSON c]

instance  (FromJSON a, FromJSON b, FromJSON c) ⇒ FromJSON (a, b, c) where
    fromJSON (Array [va, vb, vc]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        return (a,b,c)
    fromJSON other      = fail ("cannot decode (a,b,c) from " ++ show other)


instance   (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d) ⇒ ToJSON (a, b, c, d) where
    toJSON (a,b,c,d) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d]

instance   (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d) ⇒ FromJSON (a, b, c, d) where
    fromJSON (Array [va, vb, vc, vd]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        return (a,b,c,d)
    fromJSON other      = fail ("cannot decode (a,b,c,d) from " ++ show other)


instance   (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e) ⇒ ToJSON (a, b, c, d, e) where
    toJSON (a,b,c,d,e) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e]

instance   (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e) ⇒ FromJSON (a, b, c, d, e) where
    fromJSON (Array [va, vb, vc, vd, ve]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        return (a,b,c,d,e)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e) from " ++ show other)


instance   (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f) ⇒ ToJSON (a, b, c, d, e, f) where
    toJSON (a,b,c,d,e,f) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f]

instance   (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f) ⇒ FromJSON (a, b, c, d, e, f) where
    fromJSON (Array [va, vb, vc, vd, ve, vf]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        return (a,b,c,d,e,f)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f) from " ++ show other)


instance   (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g) ⇒  ToJSON (a, b, c, d, e, f, g) where
    toJSON (a,b,c,d,e,f,g) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g]

instance   (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g) ⇒ FromJSON (a, b, c, d, e, f, g) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        return (a,b,c,d,e,f,g)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g) from " ++ show other)


instance   (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h) ⇒ ToJSON (a, b, c, d, e, f, g, h) where
    toJSON (a,b,c,d,e,f,g,h) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h]

instance   (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h) ⇒ FromJSON  (a, b, c, d, e, f, g, h) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        return (a,b,c,d,e,f,g,h)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h) from " ++ show other)


instance  (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i) ⇒ ToJSON  (a, b, c, d, e, f, g, h, i) where
    toJSON (a,b,c,d,e,f,g,h,i) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i) ⇒ FromJSON  (a, b, c, d, e, f, g, h, i) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        return (a,b,c,d,e,f,g,h,i)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j) ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j) where
    toJSON (a,b,c,d,e,f,g,h,i,j) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j) ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        return (a,b,c,d,e,f,g,h,i,j)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k) ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k) ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        return (a,b,c,d,e,f,g,h,i,j,k)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l)
                    ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l)
                    ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        return (a,b,c,d,e,f,g,h,i,j,k,l)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m)
                    ⇒  ToJSON (a, b, c, d, e, f, g, h, i, j, k, l, m) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m)
                    ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        return (a,b,c,d,e,f,g,h,i,j,k,l,m)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n)
                    ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n)
                    ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o)
                    ⇒  ToJSON (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o)
                    ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p)
                    ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p)
                    ⇒  FromJSON (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p, ToJSON q)
                    ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p,
                            toJSON q]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p, FromJSON q)
                    ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp, vq]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        q ← fromJSON vq
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p, ToJSON q, ToJSON r)
                    ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p,
                            toJSON q, toJSON r]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p, FromJSON q, FromJSON r)
                    ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp, vq, vr]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        q ← fromJSON vq
        r ← fromJSON vr
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p, ToJSON q, ToJSON r,
                    ToJSON s)
                    ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p,
                            toJSON q, toJSON r, toJSON s]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p, FromJSON q, FromJSON r,
                    FromJSON s)
                    ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp, vq, vr, 
                                             vs]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        q ← fromJSON vq
        r ← fromJSON vr
        s ← fromJSON vs
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p, ToJSON q, ToJSON r,
                    ToJSON s, ToJSON t)
                ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p,
                            toJSON q, toJSON r, toJSON s, toJSON t]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p, FromJSON q, FromJSON r,
                    FromJSON s, FromJSON t)
                ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp, vq, vr, 
                                             vs, vt]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        q ← fromJSON vq
        r ← fromJSON vr
        s ← fromJSON vs
        t ← fromJSON vt
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p, ToJSON q, ToJSON r,
                    ToJSON s, ToJSON t, ToJSON u)
                ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p,
                            toJSON q, toJSON r, toJSON s, toJSON t,
                            toJSON u]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p, FromJSON q, FromJSON r,
                    FromJSON s, FromJSON t, FromJSON u)
                ⇒ FromJSON (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp, vq, vr, 
                                             vs, vt, vu]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        q ← fromJSON vq
        r ← fromJSON vr
        s ← fromJSON vs
        t ← fromJSON vt
        u ← fromJSON vu
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p, ToJSON q, ToJSON r,
                    ToJSON s, ToJSON t, ToJSON u,
                    ToJSON v)
            ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p,
                            toJSON q, toJSON r, toJSON s, toJSON t,
                            toJSON u, toJSON v]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p, FromJSON q, FromJSON r,
                    FromJSON s, FromJSON t, FromJSON u,
                    FromJSON v)
            ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp, vq, vr, 
                                             vs, vt, vu, vv]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        q ← fromJSON vq
        r ← fromJSON vr
        s ← fromJSON vs
        t ← fromJSON vt
        u ← fromJSON vu
        v ← fromJSON vv
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p, ToJSON q, ToJSON r,
                    ToJSON s, ToJSON t, ToJSON u,
                    ToJSON v, ToJSON w)
            ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p,
                            toJSON q, toJSON r, toJSON s, toJSON t,
                            toJSON u, toJSON v, toJSON w]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p, FromJSON q, FromJSON r,
                    FromJSON s, FromJSON t, FromJSON u,
                    FromJSON v, FromJSON w)
            ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp, vq, vr, 
                                             vs, vt, vu, vv, vw]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        q ← fromJSON vq
        r ← fromJSON vr
        s ← fromJSON vs
        t ← fromJSON vt
        u ← fromJSON vu
        v ← fromJSON vv
        w ← fromJSON vw
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p, ToJSON q, ToJSON r,
                    ToJSON s, ToJSON t, ToJSON u,
                    ToJSON v, ToJSON w, ToJSON x)
            ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p,
                            toJSON q, toJSON r, toJSON s, toJSON t,
                            toJSON u, toJSON v, toJSON w, toJSON x]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p, FromJSON q, FromJSON r,
                    FromJSON s, FromJSON t, FromJSON u,
                    FromJSON v, FromJSON w, FromJSON x)
            ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp, vq, vr, 
                                             vs, vt, vu, vv, vw, vx]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        q ← fromJSON vq
        r ← fromJSON vr
        s ← fromJSON vs
        t ← fromJSON vt
        u ← fromJSON vu
        v ← fromJSON vv
        w ← fromJSON vw
        x ← fromJSON vx
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p, ToJSON q, ToJSON r,
                    ToJSON s, ToJSON t, ToJSON u,
                    ToJSON v, ToJSON w, ToJSON x,
                    ToJSON y)
            ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p,
                            toJSON q, toJSON r, toJSON s, toJSON t,
                            toJSON u, toJSON v, toJSON w, toJSON x,
                            toJSON y]

instance (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p, FromJSON q, FromJSON r,
                    FromJSON s, FromJSON t, FromJSON u,
                    FromJSON v, FromJSON w, FromJSON x,
                    FromJSON y)
            ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp, vq, vr, 
                                             vs, vt, vu, vv, vw, vx, vy]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        q ← fromJSON vq
        r ← fromJSON vr
        s ← fromJSON vs
        t ← fromJSON vt
        u ← fromJSON vu
        v ← fromJSON vv
        w ← fromJSON vw
        x ← fromJSON vx
        y ← fromJSON vy
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y) from " ++ show other)


instance (ToJSON a, ToJSON b, ToJSON c,
                    ToJSON d, ToJSON e, ToJSON f,
                    ToJSON g, ToJSON h, ToJSON i,
                    ToJSON j, ToJSON k, ToJSON l,
                    ToJSON m, ToJSON n, ToJSON o,
                    ToJSON p, ToJSON q, ToJSON r,
                    ToJSON s, ToJSON t, ToJSON u,
                    ToJSON v, ToJSON w, ToJSON x,
                    ToJSON y, ToJSON z)
            ⇒ ToJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z) where
    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z) = Array [
                            toJSON a, toJSON b, toJSON c, toJSON d,
                            toJSON e, toJSON f, toJSON g, toJSON h,
                            toJSON i, toJSON j, toJSON k, toJSON l,
                            toJSON m, toJSON n, toJSON o, toJSON p,
                            toJSON q, toJSON r, toJSON s, toJSON t,
                            toJSON u, toJSON v, toJSON w, toJSON x,
                            toJSON y, toJSON z]

instance  (FromJSON a, FromJSON b, FromJSON c,
                    FromJSON d, FromJSON e, FromJSON f,
                    FromJSON g, FromJSON h, FromJSON i,
                    FromJSON j, FromJSON k, FromJSON l,
                    FromJSON m, FromJSON n, FromJSON o,
                    FromJSON p, FromJSON q, FromJSON r,
                    FromJSON s, FromJSON t, FromJSON u,
                    FromJSON v, FromJSON w, FromJSON x,
                    FromJSON y, FromJSON z)
            ⇒ FromJSON  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z) where
    fromJSON (Array [va, vb, vc, vd, ve, vf, vg, vh, vi, 
                                             vj, vk, vl, vm, vn, vo, vp, vq, vr, 
                                             vs, vt, vu, vv, vw, vx, vy, vz]) = do
        a ← fromJSON va
        b ← fromJSON vb
        c ← fromJSON vc
        d ← fromJSON vd
        e ← fromJSON ve
        f ← fromJSON vf
        g ← fromJSON vg
        h ← fromJSON vh
        i ← fromJSON vi
        j ← fromJSON vj
        k ← fromJSON vk
        l ← fromJSON vl
        m ← fromJSON vm
        n ← fromJSON vn
        o ← fromJSON vo
        p ← fromJSON vp
        q ← fromJSON vq
        r ← fromJSON vr
        s ← fromJSON vs
        t ← fromJSON vt
        u ← fromJSON vu
        v ← fromJSON vv
        w ← fromJSON vw
        x ← fromJSON vx
        y ← fromJSON vy
        z ← fromJSON vz
        return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z)
    fromJSON other      = fail ("cannot decode (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z) from " ++ show other)
